﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using Utility.Inspector;
using Utility.Inspector.ReorderableList;
using UnityEditor;
using Utility.Math;
using System;

namespace Utility.DataSystem
{
	public class EventActionDrawer
	{
		int allowedVariables;
		int allowedEvents;

		public EventActionDrawer (int allowedVariables = ~0, int allowedEvents = ~0)
		{
			this.allowedVariables = allowedVariables;
			this.allowedEvents = allowedEvents;
			listDrawer = new ListDrawer (this);
		}

		ListDrawer listDrawer;


		public void Draw (List<EventActionSettingObject> list)
		{
			listDrawer.Draw (list, ReorderableListFlags.DisableDuplicateCommand | ReorderableListFlags.HideRemoveButtons);
		}

		public class ListDrawer : ListDrawer<EventActionSettingObject>
		{
			EventActionDrawer drawer;

			public ListDrawer (EventActionDrawer drawer) : base ()
			{
				this.drawer = drawer;
			}

			protected override EventActionSettingObject CreateItem ()
			{
				var settingObj = new EventActionSettingObject ();
				return settingObj;
			}

			float w_removeBtn = 25;
			float w_label = 50;
			float w_paramLabel => w_label + 50;
			public override void DrawItem (Rect position, int index)
			{
				var item = List[index];
				var pos = position.ResizeHeight (ReorderableListGUI.DefaultItemHeight);

				if (item != null)
				{
					int allowedFlags = 0;
					//event
					{
						Rect pos_line = pos.ShrinkRight (w_removeBtn).ShrinkHeight (2);
						Rect pos_label = pos_line.ResizeWidth (w_label);
						Rect pos_event = pos_line.ShrinkLeft (w_label);
						EditorGUI.LabelField (pos_label, "事件");
						bool invalid = item.eventName == null || !FieldCenter.ContainsEvent (item.eventName);
						using (GUIColorScope.New (invalid, Color.red))
						{
							var drawData = FieldCenter.GetDrawData_Event (drawer.allowedEvents);
							item.eventName = EditorGUIEX.StringPopupField (pos_event, "", item.eventName, drawData.keys, drawData.shownames);
						}
						allowedFlags = FieldCenter.GetEvent (item.eventName)?.AllowedContextFlags ?? 0;
						allowedFlags |= drawer.allowedVariables;
						pos = pos.ShiftUp ();
					}
					//variables
					{
						if (item.variableParams.Count != item.variables.Count)
						{
							item.variableParams.Clear ();
							for (int i = 0; i < item.variables.Count; i++)
							{
								item.variableParams.Add (new EventActionSettingObject.VariableParams ());
							}
						}

						char varName = 'a';
						var variables = item.variables;
						for (int i = 0; i < variables.Count; i++)
						{
							Rect pos_line = pos.ShrinkHeight (2);
							EditorGUI.LabelField (pos_line.ResizeWidth (w_label), $"设 {varName} = ");

							//popup
							string variable = variables[i];
							var drawData = FieldCenter.GetDrawData_Variable (allowedFlags);
							bool invalid = !drawData.keys.Contains (variable);
							using (GUIColorScope.New (invalid, Color.red))
							{
								variables[i] = EditorGUIEX.StringPopupField (pos_line.ShrinkWidth (w_label, w_removeBtn), GUIContent.none, variable, drawData.keys, drawData.shownames);
							}

							//remove btn
							if (GUI.Button (pos_line.DockRight (w_removeBtn), "X"))
							{
								variables.RemoveAt (i);
								break;
							}
							varName++;
							if (varName == 'e')
							{
								varName++;
							}
							pos = pos.ShiftUp ();

							//params
							var fieldSetting = FieldCenter.GetField (variable);
							if (fieldSetting != null)
							{
								item.variableParams[i].parameters = DrawParam (ref pos, fieldSetting.ParamSettings, item.variableParams[i]?.parameters);
							}
						}
					}
					//conditions
					{
						var conditions = item.conditions;
						for (int i = 0; i < conditions.Count; i++)
						{
							Rect pos_line = pos.ShrinkHeight (2);
							EditorGUI.LabelField (pos_line.ResizeWidth (w_label), "若");
							//field
							bool invalid = string.IsNullOrWhiteSpace (conditions[i]);
							using (GUIColorScope.New (invalid, Color.red))
							{
								conditions[i] = EditorGUI.TextField (pos_line.ShrinkWidth (w_label, w_removeBtn), conditions[i]);
							}
							//remove btn
							if (GUI.Button (pos_line.DockRight (w_removeBtn), "X"))
							{
								conditions.RemoveAt (i);
								break;
							}
							pos = pos.ShiftUp ();
						}
					}
					//actions
					{
						var actions = item.actions;
						for (int i = 0; i < actions.Count; i++)
						{
							Rect pos_line = pos.ShrinkHeight (2);
							Rect pos_label = pos_line.DockLeft (w_label);
							Rect pos_popup = pos_line.ShrinkLeft (w_label).ShrinkRight (w_removeBtn);
							Rect pos_removeBtn = pos_line.DockRight (w_removeBtn);

							var action = actions[i];
							var actionSetting = FieldCenter.GetAction (action.actionName);
							//label
							EditorGUI.LabelField (pos_label, "执行");
							//popup
							bool invalid = action.actionName == null || !FieldCenter.ContainsAction (action.actionName);
							using (GUIColorScope.New (invalid, Color.red))
							{
								var drawData = FieldCenter.GetDrawData_Action (allowedFlags);
								action.actionName = EditorGUIEX.StringPopupField (pos_popup, "", action.actionName, drawData.keys, drawData.shownames);
							}
							//remove btn
							if (GUI.Button (pos_removeBtn, "X"))
							{
								actions.RemoveAt (i);
								break;
							}
							pos = pos.ShiftUp ();

							//params
							if (actionSetting != null)
							{
								action.parameters = DrawParam (ref pos, actionSetting.ParamSettings, action.parameters);
							}
						}
					}
					//buttons
					{
						pos = pos.ResizeHeight (ReorderableListGUI.DefaultItemHeight);
						var pos_btn = pos.DockRight (80);
						if (GUI.Button (pos_btn.ShrinkHeight (2), "添加功能"))
						{
							item.actions.Add (new EventActionSettingObject.Action ());
						}
						pos_btn = pos_btn.ShiftLeft ();
						if (GUI.Button (pos_btn.ShrinkHeight (2), "添加条件"))
						{
							item.conditions.Add ("");
						}
						pos_btn = pos_btn.ShiftLeft ();
						if (GUI.Button (pos_btn.ShrinkHeight (2), "添加变量"))
						{
							item.variables.Add ("");
						}
					}
				}


			}

			public override float GetItemHeight (int index)
			{
				float h_line = ReorderableListGUI.DefaultItemHeight;
				var setting = List[index];
				//event
				float h = h_line;
				//variables
				foreach (var v in setting.variables)
				{
					h += h_line;

					var f = FieldCenter.GetField (v);
					h += h_line * (f?.ParamCount ?? 0);
				}
				//conditions
				h += h_line * setting.conditions.Count;
				//actions
				foreach (var action in setting.actions)
				{
					h += h_line;

					var a = FieldCenter.GetAction (action.actionName);
					h += h_line * (a?.ParamCount ?? 0);
				}
				//buttons
				h += h_line;
				return h;
			}

			ActionParam[] DrawParam (ref Rect pos, IList<FieldParamSetting> settingList, ActionParam[] paramList)
			{
				int p_count = settingList.Count;
				if (paramList == null || paramList.Length != p_count)
				{
					paramList = new ActionParam[p_count];
				}

				for (int i = 0; i < settingList.Count; i++)
				{
					var setting = settingList[i];

					var pos_line = pos.ShrinkHeight (2).ShrinkRight (w_removeBtn);
					var pos_label = pos_line.DockLeft (w_paramLabel);
					var pos_expression = pos_line.ShrinkLeft (w_paramLabel);

					string showname = $"[{i}]{(string.IsNullOrWhiteSpace (setting.showName) ? $"参数" : setting.showName)}";
					//label
					EditorGUI.LabelField (pos_label, showname);

					//expression
					var param = paramList[i] ?? (paramList[i] = new ActionParam ());
					bool invalid = string.IsNullOrEmpty (param.str);
					using (GUIColorScope.New (invalid, Color.red))
					{
						if (setting.type.IsSubclassOf (typeof (Setting)))
						{
							param.str = EditorGUIEX.StringPopupField (pos_expression, "", param.str, SettingCenter.GetNameArray (setting.type));
							param.isExpression = false;
						}
						else
						{
							param.str = EditorGUI.TextField (pos_expression, param.str);
							param.isExpression = setting.type != typeof (string);
						}
					}
					pos = pos.ShiftUp ();
				}
				return paramList;
			}
		}
	}
}